module top_module (
    input clk,
    input resetn,    // active-low synchronous reset
    input x,
    input y,
    output f,
    output g
); 

    /*
    localparam FSM_W  = 10;
    localparam FSM_W1 = FSM_W - 1'b1;

    reg [FSM_W1:0]   state;
    reg [FSM_W1:0]   nxt_state;

    localparam  IDLE      = 0;
    localparam  AFT_RST   = 1;
    localparam  STRT_X_MNT= 2;
    localparam  X_1       = 3;
    localparam  X_0       = 4;
    localparam  X_10      = 5;
    localparam  X_101     = 6;
    localparam  Y_S0      = 7;
    localparam  G_O0      = 8;
    localparam  G_O1      = 9;

    // State transition logic (combinational)
    always @(*) begin
        nxt_state[IDLE   ]          =   1'b0; // never reach for nxt_state
        nxt_state[AFT_RST]          =   (state[IDLE   ]);
        nxt_state[STRT_X_MNT]       =   (state[AFT_RST]);
        nxt_state[X_1    ]          =   (state[STRT_X_MNT] &&  x) || (state[X_1    ] &&  x) || (state[X_0    ] &&  x);
        nxt_state[X_0    ]          =   (state[STRT_X_MNT] && ~x) || (state[X_10   ] && ~x) || (state[X_0    ] && ~x);
        nxt_state[X_10   ]          =   (state[X_1    ] && ~x);
        nxt_state[X_101  ]          =   (state[X_10   ] &&  x);
        nxt_state[Y_S0   ]          =   (state[X_101  ] && ~y);
        nxt_state[G_O0   ]          =   (state[Y_S0   ] && ~y) || state[G_O0   ];
        nxt_state[G_O1   ]          =   (state[Y_S0   ] &&  y) || (state[X_101  ] &&  y) || state[G_O1   ];
    end

    // State flip-flops (sequential)
    always @(posedge clk) begin
        if(~resetn)
            state   <=  'b1; //IDLE
        else begin
            state   <=  nxt_state;
        end  
    end

    //output logic
    assign  f    =   state[AFT_RST];
    assign  g    =   (state[X_101] || state[G_O1] || state[Y_S0]) ? 1'b1 : 1'b0;
    */

    parameter IDLE = 4'd0, S1 = 4'd1, S2 = 4'd2, S3 = 4'd3, S4 = 4'd4;
    parameter S5 = 4'd5, FOREVER_ONE = 4'd6, FOREVER_ZERO = 4'd7;
    parameter F_OUT = 4'd8;
    
    reg	[3:0]	current_state;
    reg	[3:0]	next_state;
    
    always@(posedge clk)begin
        if(resetn == 1'b0)begin
            current_state <= IDLE;
        end
        else begin
            current_state <= next_state;
        end
    end
    
    always@(*)begin
        case(current_state)
            IDLE:begin
                next_state = F_OUT;
            end
            F_OUT:begin
                next_state = S1;
            end
            S1:begin
                next_state = x ? S2 : S1;
            end
            S2:begin
                next_state = x ? S2 : S3;
            end
            S3:begin
                next_state = x ? S4 : S1;
            end  
            S4:begin
                next_state = y ? FOREVER_ONE : S5;
            end
            S5:begin
                next_state = y ? FOREVER_ONE : FOREVER_ZERO;
            end
            FOREVER_ONE:begin
                next_state = FOREVER_ONE;
            end
            FOREVER_ZERO:begin
                next_state = FOREVER_ZERO;
            end
            default:begin
                next_state = IDLE;
            end
        endcase
    end
    
    assign f = (current_state == F_OUT);
    assign g = (current_state == S4 || current_state == S5 || current_state == FOREVER_ONE);

endmodule
